Skip to content

feat(external-agents): add crate foundation for CLI agent bridge#566

Open
penso wants to merge 3 commits intomainfrom
beaded-perch
Open

feat(external-agents): add crate foundation for CLI agent bridge#566
penso wants to merge 3 commits intomainfrom
beaded-perch

Conversation

@penso
Copy link
Copy Markdown
Collaborator

@penso penso commented Apr 6, 2026

Summary

  • Introduces crates/external-agents/ — new workspace crate for connecting Moltis chat sessions to external CLI coding agents (Claude Code, opencode, Codex CLI, Pi agent, ACP)
  • Adds core types (AgentTransportKind, ExternalAgentEvent, ContextSnapshot, BridgeState), transport traits (ExternalAgentTransport, ExternalAgentSession), registry for runtime dispatch, and delta sync engine with compaction reconciliation
  • Wires into existing workspace: ExternalAgentsConfig in config schema/validate/template, ExternalAgentService trait in service-traits Services bundle, external_agent_kind/external_session_id on SessionEntry

Validation

Completed

  • cargo check --workspace — clean
  • cargo +nightly-2025-11-30 fmt --all -- --check — clean
  • cargo clippy -p moltis-external-agents --all-targets -- -D warnings — clean
  • taplo fmt — clean
  • 9 unit tests pass (bridge delta sync scenarios + registry dispatch)
  • 178 config tests pass (schema, validation, template)
  • 90 session tests pass (metadata with new fields)
  • 4 service-traits tests pass

Remaining

  • ./scripts/local-validate.sh <PR_NUMBER> — full validation suite
  • just test — full workspace test suite

Manual QA

This is Phase 1 (foundation only) — no user-visible behavior changes yet. Runtime stubs return "not yet implemented" errors. Gateway routing (Phase 5) and Web UI (Phase 6) are future work.

To verify the new config section parses:

[external_agents]
enabled = true

[external_agents.agents.claude-code]
timeout_secs = 300

🤖 Generated with Claude Code

Introduce `crates/external-agents/` with core types, traits, and
session bridge logic for connecting Moltis chat sessions to external
CLI coding agents (Claude Code, opencode, Codex, Pi agent, ACP).

New crate provides:
- `ExternalAgentTransport` / `ExternalAgentSession` traits
- `ExternalAgentRegistry` for runtime dispatch
- Delta sync engine with compaction reconciliation (4 scenarios)
- Feature-gated runtime stubs for 5 agent kinds
- `ExternalAgentError` with thiserror

Wires into existing workspace:
- `ExternalAgentsConfig` added to `MoltisConfig` schema
- `build_schema_map()` and config template updated
- `ExternalAgentService` trait + noop added to `Services` bundle
- `external_agent_kind` / `external_session_id` on `SessionEntry`

Entire-Checkpoint: 3e13cf1c768d
@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq bot commented Apr 6, 2026

Merging this PR will not alter performance

✅ 39 untouched benchmarks
⏩ 5 skipped benchmarks1


Comparing beaded-perch (032b0e2) with main (16eb4eb)

Open in CodSpeed

Footnotes

  1. 5 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 6, 2026

Greptile Summary

Introduces the moltis-external-agents foundation crate (core types, transport trait, registry, delta sync/compaction engine) and wires it into config, service-traits, and session metadata as a no-op Phase 1 scaffold — all runtime stubs return "not yet implemented" and no user-visible behavior changes ship yet.

Confidence Score: 5/5

Safe to merge — all findings are P2 style and maintenance suggestions with no current defects

All five concerns from prior review rounds have been addressed: no Other catch-all in error.rs, tracing instrumented on runtimes, synced_message_count naming corrected, ExternalAgentKind is a typed mirror enum, unused moltis-agents dep removed. Remaining findings are a missing semantic validation rule per CLAUDE.md and a future migration hygiene note — neither blocks merge.

crates/config/src/validate.rs (semantic warning for unknown agent-kind keys); crates/sessions/src/metadata.rs (From will need updating when DB migration lands)

Important Files Changed

Filename Overview
crates/external-agents/src/bridge.rs Delta sync engine with compaction reconciliation; test comment in moltis_compaction_detected_by_hash says 'same count' when count actually changes (5 → 6)
crates/external-agents/src/types.rs Core types (AgentTransportKind, BridgeState, ContextSnapshot, ExternalAgentEvent) with proper serde, Display, and FromStr impls
crates/external-agents/src/registry.rs Runtime registry with kind-indexed HashMap dispatch; tracing instrumentation correctly gated behind feature flag
crates/external-agents/src/transport.rs Clean async trait definitions for ExternalAgentTransport and ExternalAgentSession; streaming return type for send_prompt
crates/external-agents/src/error.rs Well-typed error enum with named variants (ProcessSpawn, Protocol); no catch-all Other variant
crates/external-agents/Cargo.toml New crate with opt-out feature defaults; all deps reference workspace correctly; no version pins in crate Cargo.toml
crates/config/src/schema.rs Adds ExternalAgentsConfig with string-keyed agents map; agent kind key strings are unvalidated against known enum values
crates/config/src/validate.rs Schema map updated for external_agents; no semantic warning added for unknown agent kind key strings per CLAUDE.md requirement
crates/sessions/src/metadata.rs Adds ExternalAgentKind mirror enum and two new SessionEntry fields; From silently defaults both fields to None — correct now but needs updating when DB migration lands
crates/service-traits/src/lib.rs ExternalAgentService trait and NoopExternalAgentService added; wired into Services bundle and Default impl; consistent with existing service patterns
crates/external-agents/src/runtimes/claude_code.rs Phase 1 stub with correct tracing instrumentation; which::which for PATH availability check
crates/external-agents/src/runtimes/acp.rs Phase 1 stub with configurable binary name via constructor; tracing attributes correctly applied

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Chat Session] -->|send prompt| B[ExternalAgentRegistry]
    B -->|lookup AgentTransportKind| C{Transport Found?}
    C -- No --> D[NoRuntimeForKind error]
    C -- Yes --> E[ExternalAgentTransport::start_session]
    E --> F[ExternalAgentSession]
    F --> G[compute_delta]
    G --> H{BridgeState.initialized?}
    H -- No --> I[Full context snapshot\nstart_index=0]
    H -- Yes --> J{CLI alive?}
    J -- No --> K[CliCompacted\nsnapshot=true]
    J -- Yes --> L{count < synced_message_count?}
    L -- Yes --> M[MoltisCompacted\nsnapshot=true]
    L -- No --> N{hash mismatch at tail?}
    N -- Yes --> M
    N -- No --> O[Delta sync\nstart_index=synced_message_count]
    I --> P[send_prompt + ContextSnapshot]
    O --> P
    P --> Q[Stream ExternalAgentEvent]
    Q --> R[advance_bridge_state]
    R --> S[Update synced_message_count\n+ last_synced_tail_hash]
Loading

Reviews (6): Last reviewed commit: "fix(external-agents): typed enum for ses..." | Re-trigger Greptile

penso added 2 commits April 6, 2026 14:08
- Remove unused `moltis-agents` dependency
- Rename `last_synced_message_index` → `synced_message_count` (stores
  a count, not a 0-based index)
- Replace `Other(#[from] anyhow::Error)` catch-all with concrete
  `ProcessSpawn` and `Protocol` variants
- Add `#[tracing::instrument]` on registry async methods (feature-gated)
- Document `external_agent_kind: Option<String>` as a serialization
  boundary (sessions crate has no dep on external-agents)

Entire-Checkpoint: 433a46b5f3fb
- Replace `external_agent_kind: Option<String>` with typed
  `Option<ExternalAgentKind>` enum in SessionEntry (mirror enum in
  moltis-sessions to avoid cross-crate dep)
- Export `ExternalAgentKind` from moltis-sessions
- Add `#[tracing::instrument]` (feature-gated) to all runtime transport
  `is_available` and `start_session` methods

Entire-Checkpoint: 016437bf01ff
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant